package com.xflib.framework.util;

import com.xflib.framework.log.StreamGobbler;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.scp.client.ScpClient;
import org.apache.sshd.scp.client.ScpClientCreator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * @author koradji@163.com
 * @date 2023/10/24
 */
public class ScpUtil {
    Logger logger = LoggerFactory.getLogger(ScpUtil.class);

    public final String REMOTE_PATH="/tmp/";

    private String host = "192.168.67.39";
    private Integer port = 22;
    private String username = "root";
    private String password = "***********";

//    public ScpUtil setBuffer(CommandLineCallable<String> buffer) {
//        //this.buffer = buffer;
//        return this;
//    }

//    private CommandLineCallable<String> buffer = new CommandLineConsole();

    SshClient client;
    ClientSession session;
    boolean isSuccess = false;

    private int exitStatus = 1;

    private ScpUtil(){}

    public static ScpUtil create(String host, Integer port, String username, String password){
        ScpUtil scpUtil = new ScpUtil();
        scpUtil.host=host;
        scpUtil.port=port;
        scpUtil.username=username;
        scpUtil.password=password;
        return scpUtil;
    }

    public ScpUtil open() throws IOException{
        long startTime = System.currentTimeMillis();

        StreamGobbler.appendWithDebug(this.logger,
                String.format("[INFO] connecting %s@%s:%d", username, host, port));
        try {
            // 创建 SSH客户端
            client = SshClient.setUpDefaultClient();
            // 启动 SSH客户端
            client.start();
            // 通过主机IP、端口和用户名，连接主机，获取Session
            session = client.connect(username, host, port).verify().getSession();
            // 给Session添加密码
            session.addPasswordIdentity(password);
            // 校验用户名和密码的有效性
            isSuccess = session.auth().verify().isSuccess();
        }catch(Exception e){
            System.out.println("======================open: "+e.getMessage());
        } finally {
            StreamGobbler.appendWithDebug(this.logger,
                    String.format("[INFO] connected %s and cost time %.1fs.",
                            isSuccess?"success":"failed",(System.currentTimeMillis() - startTime) / 1000.0 ));

        }

        return this;
    }
    public ScpUtil close() throws IOException {
        long startTime = System.currentTimeMillis();

        StreamGobbler.appendWithDebug(this.logger, String.format("[INFO] disconnecting %s@%s:%d", username, host, port));
        try {
            // 关闭 Session
            if (session != null && session.isOpen()) {
                session.close();
            }

            // 延时防止二次调用通道关闭，这是有效的
            try{Thread.sleep(1000);}catch(InterruptedException ee){Thread.currentThread().interrupt();}

            // 关闭 SSH客户端
            if (client != null && client.isOpen()) {
                client.stop();
                client.close();
            }
            isSuccess = false;

        }catch(Exception e){
            System.out.println("======================close: "+e.getMessage());
        }finally {
            StreamGobbler.appendWithDebug(this.logger,
                    String.format("[INFO] disconnected %s and cost time: %.1fs.",
                            !isSuccess?"success":"failed",(System.currentTimeMillis() - startTime) / 1000.0 ));
            isSuccess = false;
            session = null;
            client =null;
        }

        return this;
    }

    public ScpUtil exec(String local) throws Exception {
        return this.exec(local, REMOTE_PATH);
    }
    public ScpUtil exec(String local, String remote) throws IOException {
        long startTime = System.currentTimeMillis();

        try {
//            this.buffer.appendBufferWithDebug(this.logger,
//                    String.format("[INFO] connecting %s@%s:%d", username, host, port));
//            try {
//                // 创建 SSH客户端
//                client = SshClient.setUpDefaultClient();
//                // 启动 SSH客户端
//                client.start();
//                // 通过主机IP、端口和用户名，连接主机，获取Session
//                session = client.connect(username, host, port).verify().getSession();
//                // 给Session添加密码
//                session.addPasswordIdentity(password);
//                // 校验用户名和密码的有效性
//                isSuccess = session.auth().verify().isSuccess();
//            }catch(Exception e){
//                System.out.println("======================open: "+e.getMessage());
//            } finally {
//                this.buffer.appendBufferWithDebug(this.logger,
//                        String.format("[INFO] connected %s and cost time %.1fs.",
//                                isSuccess?"success":"failed",(System.currentTimeMillis() - startTime) / 1000.0 ));
//
//            }

            if (isSuccess) {
                exitStatus = 1;

                StreamGobbler.appendWithDebug(this.logger,
                        String.format("[INFO] scp %s %s@%s:%d/%s", local, username, host, port, remote));

                ScpClient scpClient=null;
                try {
                    // 创建 SCP 客户端
                    scpClient = ScpClientCreator.instance().createScpClient(session);
                    // ScpClient.Option.Recursive：递归copy，可以将子文件夹和子文件遍历copy
                    scpClient.upload(local, remote, ScpClient.Option.Recursive);
                    exitStatus = 0;
                } finally {
                    // 释放 SCP客户端
                    if ( null != scpClient) {
                        //scpClient.getClientSession().close();
                        scpClient = null;
                    }
                }
            }
        }catch(Exception e){
            System.out.println("======================exec: "+e.getMessage());
        } finally {
            StreamGobbler.appendWithDebug(this.logger,
                    String.format("[%s] Exec Exit %d, Total Cost time: %.1fs.", exitStatus==0?"INFO":"ERROR",
                            exitStatus, (System.currentTimeMillis() - startTime) / 1000.0 ));
        }


//        this.buffer.appendBufferWithDebug(this.logger, String.format("[INFO] disconnecting %s@%s:%d", username, host, port));
//        try {
//            // 关闭 Session
//            if (session != null && session.isOpen()) {
//                session.close();
//            }
//
//            // 关闭 SSH客户端
//            if (client != null && client.isOpen()) {
//                client.stop();
//                client.close();
//            }
//            isSuccess = false;
//
//        }catch(Exception e){
//            System.out.println("======================close: "+e.getMessage());
//        }finally {
//            this.buffer.appendBufferWithDebug(this.logger,
//                    String.format("[INFO] disconnected %s and cost time: %.1fs.",
//                            !isSuccess?"success":"failed",(System.currentTimeMillis() - startTime) / 1000.0 ));
//            isSuccess = false;
//            session = null;
//            client =null;
//        }

        return this;
    }

    public int getExitStatus() {
        return exitStatus;
    }
}
